package com.css.sword.knowing.toolkit.file;

import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.RandomAccessFile;
import java.nio.channels.FileChannel;
import java.nio.channels.FileLock;

/**
 * @author 作者 E-mail:caihx@css.com.cn
 * @version 创建时间：2017年2月22日 下午2:13:55
 * 
 */
public class CssFileOption {
    private RandomAccessFile fis = null;
    private FileChannel fChannel = null;
    private FileLock fLock = null;

    /**
     * 尝试对文件上读写锁
     * @param fpath
     * 文件路径
     * @param retry
     * 重试次数
     * @return
     * true：上锁成功， false：上锁失败
     */
    public boolean tryLock(String fpath, int retry) {
        try {
            fis = new RandomAccessFile(fpath, "rw");

            fChannel = fis.getChannel();

            int index = 1;
            while (null == fLock && retry > 0) {
                try {
                    fLock = fChannel.tryLock();
                } catch (Exception e) {
                }
                if (null == fLock) {
                    System.out.println("文件" + fpath + "正在被占用，休眠2000毫秒后进行第" + index + "次尝试");
                    try {
                        Thread.sleep(1000);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
                else
                {
                    break;
                }
                index++;
                retry--;
            }

            if (retry <= 0 && null == fLock) {
                unlock();
                return false;
            }
            return true;
        } catch (FileNotFoundException e1) {
            // TODO Auto-generated catch block
            e1.printStackTrace();
        }
        return false;
    }

    /**
     * 对文件加读写锁
     * @param fpath
     * 文件路径
     * @param retry
     * 重试次数
     * @return
     * true：加锁成功，加锁失败
     */
    public boolean lock(String fpath, int retry) {
        try {
            fis = new RandomAccessFile(fpath, "rw");

            fChannel = fis.getChannel();
            int index = 1;
            while (null == fLock && retry > 0) {
                try {
                    fLock = fChannel.lock();
                } catch (Exception e) {
                }
                if (null == fLock) {
                    System.out.println("文件" + fpath + "正在被占用，休眠1000毫秒后进行第" + index + "次尝试");
                    try {
                        Thread.sleep(1000);
                    } catch (InterruptedException e) {
                        // TODO Auto-generated catch block
                        e.printStackTrace();
                    }
                }
                else
                {
                    break;
                }

                index++;
                retry--;
            }

            if (retry <= 0 && null == fLock) {
                unlock();
                return false;
            }
            return true;
        } catch (FileNotFoundException e1) {
            e1.printStackTrace();
        }
        return false;
    }

    /**
     * 获取文件的句柄
     * @return
     * 返回文件句柄
     */
    public RandomAccessFile getFileHandle() {
        return fis;
    }

    /**
     * 清除当前的锁
     */
    public void clear() {
        try {
            fChannel.truncate(0);
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }
    
    /**
     * 解锁
     */
    public void unlock() {
        if (fLock != null) {
            try {
                fLock.release();
                fLock = null;
            } catch (IOException e) {
                e.printStackTrace();
            }
        }

        if (fChannel != null) {
            try {
                fChannel.close();
                fChannel = null;
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        if (fis != null) {
            try {
                fis.close();
                fis = null;
            } catch (IOException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }
    }
}
